#include "PlSDLMixer.h"
#include "plsdlmixerlua.h"
#include "SDL_mixer.h"
#include "../core/LuaUtils.h"

RegisterCppObj<PlSDLMixer> g_register_plsdlmixer_object;

PlSDLMixer::PlSDLMixer()
{
	_initted = false;
}

// Return the c++ type id
int PlSDLMixer::getCppTypeId()
{
	return PLSDLMIXER_OBJ_ID;
}

// Returns whether this can be cast to a given type
bool PlSDLMixer::isType(int id)
{
	return id == PLSDLMIXER_OBJ_ID;
}

// Return the c++ type as a string 
std::string PlSDLMixer::getCppTypeName()
{
	return "PlSDLMixer";
}

// returns a description of this thing
std::string PlSDLMixer::getDescription()
{
	return "SDL Mixer Bindings";
}

// create another one of these
AbstractObject* PlSDLMixer::newInstance()
{
	return new PlSDLMixer();
}

// init & update
void PlSDLMixer::init()
{
	// no special init
}

void PlSDLMixer::update(double dt)
{
	// no special update
}

// push its static functions into the given lua table
void PlSDLMixer::pushStaticFuncs(lua_State* L)
{
	// push superclass static functions...
	AbstractObject::pushStaticFuncs(L);

	// just push these static funcs...
	PlSDLMixerLua::pushStaticFuncs(L);

	static const struct luaL_Reg mylib [] = {
		{"InitMixer", li_initMixer},
		{"InitMixerDefaultSettings", li_initMixerDefaultSettings},
		{"LoadWAV", li_loadWAV},
		{"LoadMUS", li_loadMUS},
		{"DeleteChunk", li_deleteChunk},
		{"DeleteMusic", li_deleteMusic},
		{NULL, NULL}  /* sentinel */
	};

	// dump them into said table
	luaL_register(L, NULL, mylib);
}

PlSDLMixer::~PlSDLMixer()
{
	if(_initted)
	{
		Mix_CloseAudio();
		Mix_Quit();
	}
}

int PlSDLMixer::initMixer(int audioFreq, int numChannels, int chunkSize)
{
	if(_initted)
	{
		Mix_CloseAudio();
	}
	// Init the SDL mixer stuff...
	Mix_Init(MIX_INIT_OGG | MIX_INIT_MP3);
	Mix_OpenAudio(audioFreq, MIX_DEFAULT_FORMAT, numChannels, chunkSize);
	_initted = true;
	return 0;
}

int PlSDLMixer::initMixerDefaultSettings()
{
	return initMixer(22050, 8, 1024);
}

//LIAG_THESE
int PlSDLMixer::loadWAV(std::string fn)
{
	Mix_Chunk* tempChunk = Mix_LoadWAV(fn.c_str());
	if(tempChunk != NULL)
	{
		int retpos = _mixChunks.add(tempChunk);
		return retpos;
	}
	else
	{
		LOG(logERROR) << "Could not load sound file " << fn;
		return -1;
	}
}

int PlSDLMixer::loadMUS(std::string fn)
{
	Mix_Music* tempChunk = Mix_LoadMUS(fn.c_str());
	if(tempChunk != NULL)
	{
		int retpos = _musChunks.add(tempChunk);
		return retpos;
	}
	else
	{
		LOG(logERROR) << "Could not load music file " << fn;
		return -1;
	}
}

int PlSDLMixer::deleteChunk(int pos)
{
	Mix_Chunk* temp = _mixChunks[pos];
	if(temp != NULL)
		Mix_FreeChunk(temp);
	_mixChunks.remove(pos);
	return 0;
}

int PlSDLMixer::deleteMusic(int pos)
{
	Mix_Music* temp = _musChunks[pos];
	if(temp != NULL)
		Mix_FreeMusic(temp);
	_musChunks.remove(pos);
	return 0;
}
//STOP_LIAG

Mix_Chunk* PlSDLMixer::getChunk(int slot)
{
	return _mixChunks[slot];
}

Mix_Music* PlSDLMixer::getMusic(int slot)
{
	return _musChunks[slot];
}

int PlSDLMixer::li_initMixer(lua_State* L)
{
	PlSDLMixer* op = (PlSDLMixer*)typeCheckUnboxAO(L,1,"PlSDLMixer");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	int a1 = (int)lua_tointeger(L, 2);
	int a2 = (int)lua_tointeger(L, 3);
	int a3 = (int)lua_tointeger(L, 4);
	int ret = op->initMixer(a1, a2, a3);
	lua_pushinteger(L, ret);
	return 1;
}


int PlSDLMixer::li_initMixerDefaultSettings(lua_State* L)
{
	PlSDLMixer* op = (PlSDLMixer*)typeCheckUnboxAO(L,1,"PlSDLMixer");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	int ret = op->initMixerDefaultSettings();
	lua_pushinteger(L, ret);
	return 1;
}


int PlSDLMixer::li_loadWAV(lua_State* L)
{
	PlSDLMixer* op = (PlSDLMixer*)typeCheckUnboxAO(L,1,"PlSDLMixer");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	std::string a1 = getSafeLuaString(L, 2);
	int ret = op->loadWAV(a1);
	lua_pushinteger(L, ret);
	return 1;
}


int PlSDLMixer::li_loadMUS(lua_State* L)
{
	PlSDLMixer* op = (PlSDLMixer*)typeCheckUnboxAO(L,1,"PlSDLMixer");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	std::string a1 = getSafeLuaString(L, 2);
	int ret = op->loadMUS(a1);
	lua_pushinteger(L, ret);
	return 1;
}


int PlSDLMixer::li_deleteChunk(lua_State* L)
{
	PlSDLMixer* op = (PlSDLMixer*)typeCheckUnboxAO(L,1,"PlSDLMixer");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	int a1 = (int)lua_tointeger(L, 2);
	int ret = op->deleteChunk(a1);
	lua_pushinteger(L, ret);
	return 1;
}


int PlSDLMixer::li_deleteMusic(lua_State* L)
{
	PlSDLMixer* op = (PlSDLMixer*)typeCheckUnboxAO(L,1,"PlSDLMixer");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	int a1 = (int)lua_tointeger(L, 2);
	int ret = op->deleteMusic(a1);
	lua_pushinteger(L, ret);
	return 1;
}
